/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game.jetclan.main.marcustestar;

import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.scene.shape.Line;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;

/**
 *
 * @author cla_marwas
 */
public class SpaceShip implements PlayableObject {

    Node mMainNode = null;
    Node mCannon = null;
    RigidBodyControl mCharacterControl = null;
    int mDirection = 0;
    Geometry mAimLineGeometry = null;
    boolean mIsBusy;
    //Ship charcteristics
    float mMaxSpeed = 40f;
    float mMaxReverseSpeed = 10f;
    float mAcceleration = 5f;
    float mReverseAcceleration = 3f;
    float mMaxRotationSpeed = 20f;
    float mRotationAccelerationSpeed = 1f;
    float mBrakeForce = 10f;
    //Current variables
    float mCurrentRotation = 0f;
    float mCurrentSpeed = 0f;

    enum SPEED {

        ACCELERATING, DEACCELERATING, BRAKING, IDLE
    }

    enum STEERING {

        LEFT, RIGHT, IDLE
    }
    SPEED mSpeedAction = SPEED.IDLE;
    STEERING mRotationAction = STEERING.IDLE;

    public SpaceShip(float aMass, BulletAppState aBulletAppState, AssetManager aAssetManager) {
        mMainNode = (Node) aAssetManager.loadModel("Models/AirCraft/AirCraft.j3o");
        //Sphere sphereSmall = new Sphere(32, 32, 0.2f, true, false);
        //cannon = 

        initAimLine(aAssetManager);
//Implement character control to set up physics        
        mCharacterControl = new RigidBodyControl(aMass);
//mCharacterControl.setGravity(new Vector3f(0,30,0));
        mMainNode.addControl(mCharacterControl);
//        mainNode.attachChild(cannon);
        mMainNode.rotate(0, -FastMath.HALF_PI, 0);
        aBulletAppState.getPhysicsSpace().add(mCharacterControl);
        //mCharacterControl.setKinematic(true);
    }

    public void setCharacteristics(float aMaxSpeed, float aMaxReverseSpeed,
            float aAcceleration,
            float aReverseAcceleration,
            float aRotationAccelerationSpeed,
            float aMaxRotationSpeed,
            float aBrakeForce) {
        
        mMaxSpeed = aMaxSpeed;
        mMaxReverseSpeed = aMaxReverseSpeed;
        mAcceleration = aAcceleration;
        mReverseAcceleration = aReverseAcceleration;
        mRotationAccelerationSpeed = aRotationAccelerationSpeed;
        mMaxRotationSpeed = aMaxRotationSpeed;
        mBrakeForce = aBrakeForce;
    }

    private void initAimLine(AssetManager aAssetManager) {

        Line aimLine = new Line(new Vector3f(0, 0, 200), mMainNode.getLocalRotation().getRotationColumn(2));

        mAimLineGeometry = new Geometry("ShipCannonAim", aimLine);
        Material myMaterial = new Material(aAssetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        myMaterial.setColor("Color", ColorRGBA.Red);
        mAimLineGeometry.setMaterial(myMaterial);

        // 
        //aimLineGeometry.setMaterial(myMaterial);
    }

    public void setLocalTranslation(Vector3f aVector3f) {
        mMainNode.setLocalTranslation(aVector3f);
    }

//    public void setRotation(float aRotation) {
//        mRotation = aRotation;
//    }
//
//    public void setSpeed(float aSpeed) {
//        mSpeed = aSpeed;
//    }
//
//    public void rotateRight(float aTpf) {
//        mRotation = FastMath.PI * aTpf * 0.5f;
//    }
//
//    public void rotateLeft(float aTpf) {
//        mRotation = -FastMath.PI * aTpf * 0.5f;
//    }
//
//    public void rotateNone() {
//        mRotation = 0;
//    }
    public void update(float aTpf) {

        if (mSpeedAction == SPEED.ACCELERATING) {
            //Add acceleration
            mCurrentSpeed += aTpf * mAcceleration;
            //Check if we have reached max speed
//            System.out.println("mCurrentSpeed: " + mCurrentSpeed);
//            System.out.println("mMaxSpeed: " + mMaxSpeed);
            mCurrentSpeed = Math.min(mCurrentSpeed, mMaxSpeed);
        } else if (mSpeedAction == SPEED.DEACCELERATING) {
            //Add acceleration
            mCurrentSpeed -= aTpf * mReverseAcceleration;
            //Check if we have reached max speed
            mCurrentSpeed = Math.max(mCurrentSpeed, -mMaxReverseSpeed);
        } else if (mSpeedAction == SPEED.BRAKING || mSpeedAction == SPEED.IDLE) {
            float brakeForce = GlobalConstants.sNaturalWindResistence * mCharacterControl.getMass();
            if (mSpeedAction == SPEED.BRAKING) {
                brakeForce = mBrakeForce;
            }

            if (mCurrentSpeed > 0) {
                mCurrentSpeed -= aTpf * brakeForce;
                if (mCurrentSpeed < 0) {
                    mCurrentSpeed = 0;
                }
            } else if (mCurrentSpeed < 0) {
                mCurrentSpeed += aTpf * brakeForce;
                if (mCurrentSpeed > 0) {
                    mCurrentSpeed = 0;
                }
            }
        }
        //Update the speed
        if (mCurrentSpeed != 0) {
            Quaternion quaternion = mMainNode.getLocalRotation();
            Vector3f zVector = quaternion.getRotationColumn(2).mult(mCurrentSpeed*0.01f);
            mMainNode.move(zVector);
        }
        
       
        //Update rotation
        if(mRotationAction == STEERING.LEFT)
        {            
            mCurrentRotation += aTpf * mRotationAccelerationSpeed;
            mCurrentRotation = Math.min(mCurrentRotation, mMaxRotationSpeed);
        } 
        else if(mRotationAction == STEERING.RIGHT)
        {            
            mCurrentRotation -= aTpf * mRotationAccelerationSpeed;
            mCurrentRotation = Math.max(mCurrentRotation, -mMaxRotationSpeed);
        } 
        else if(mRotationAction == STEERING.IDLE)
        {            
             if (mCurrentRotation > 0) {
                mCurrentRotation -= aTpf * GlobalConstants.sNaturalWindResistence;
                if (mCurrentRotation < 0) {
                    mCurrentRotation = 0;
                }
            } else if (mCurrentRotation < 0) {
                mCurrentRotation += aTpf * GlobalConstants.sNaturalWindResistence;
                if (mCurrentRotation > 0) {
                    mCurrentRotation = 0;
                }
            }
        }
        
        if (mCurrentRotation != 0) {
                mMainNode.rotate(0, mCurrentRotation, 0);
                mCurrentRotation = 0;
            }
        
        mSpeedAction = SPEED.IDLE;
        mRotationAction = STEERING.IDLE;
    }

    public void consumeAnalogAction(String name, float value, float tpf) {
        if (name.equals("Lefts")) {
            mRotationAction = STEERING.LEFT;
        } else if (name.equals("Rights")) {
            mRotationAction = STEERING.RIGHT;
        }
        else
        {
            mRotationAction = STEERING.IDLE;
        }
        if (name.equals("Forward")) {
            mSpeedAction = SPEED.ACCELERATING;
            mCharacterControl.setLinearVelocity(mMainNode.getLocalRotation().getRotationColumn(2).mult(10));
        } else if (name.equals("Backward")) {
            mSpeedAction = SPEED.DEACCELERATING;
        } else if (name.equals("Brake")) {
            mSpeedAction = SPEED.BRAKING;
            mCharacterControl.setLinearVelocity(mMainNode.getLocalRotation().getRotationColumn(1).mult(10));
        }
    }

    public void consumeAction(String name, boolean isKeyPressed, float tpf) {

        if (name.equals("ShowOrHideAimLine") && !isKeyPressed) {
            Spatial spatial = mMainNode.getChild("ShipCannonAim");
            if (spatial == null) {
                mMainNode.attachChild(mAimLineGeometry);
            } else {
                mMainNode.detachChild(mAimLineGeometry);
            }
        }
    }

    public void setIsBusy(boolean aIsBusy) {
        mIsBusy = aIsBusy;
    }

    public boolean isBusy() {
        return mIsBusy;
    }

    public Spatial getMainNode() {
        return mMainNode;
    }

    public void attachCam(Node aCamNode) {
        mMainNode.attachChild(aCamNode);
    }

    public void detachCam(Node aCamNode) {
        mMainNode.detachChild(aCamNode);
    }
}
